package com.hn.springframework.beans.support;

import com.hn.springframework.beans.config.HNBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 *  bean 配置解析器
 */
public class HNBeanDefinitionReader {

    // 配置文件中的包路径
    private final String SCAN_PACKAGE = "scanPackage";
    private Properties config = new Properties();
    // 存放扫描包下所有的 class
    private List<String> beanClasses = new ArrayList<String>();

    public HNBeanDefinitionReader(String... locations) {
        //通过URL定位找到其所对应的文件，然后转换为文件流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:","").trim());
        try {
            config.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        doScanner(config.getProperty(SCAN_PACKAGE));
    }

    public Properties getConfig(){
        return this.config;
    }

    // 扫描包
    private void doScanner(String scanPackage) {
        URL url = this.getClass().getClassLoader().getResource(scanPackage.replaceAll("\\.", "/"));
        File classPath = new File(url.getFile());
        for (File file : classPath.listFiles()) {
            if (!file.isDirectory()) {
                if (!file.getName().endsWith(".class")) { continue; }
                String className = scanPackage + "." + file.getName().replace(".class", "");
                beanClasses.add(className);
            } else {
                doScanner(scanPackage + "." + file.getName());
            }
        }
    }

    // 将 bean 封装成 BeanDefinitions
    public List<HNBeanDefinition> loadBeanDefinitions() {
        if (this.beanClasses.isEmpty()) { return null; }
        List<HNBeanDefinition> beanDefinitions = new ArrayList<HNBeanDefinition>();
        try {
            for (String beanClass : this.beanClasses) {
                Class<?> clazz = Class.forName(beanClass);
                // 接口不做实例化
                if (clazz.isInterface()) { continue; }

                beanDefinitions.add(doCreateBeanDefinition(toLowerFirstCase(clazz.getSimpleName()), clazz.getName()));

                Class<?>[] interfaces = clazz.getInterfaces();
                // TODO 接口的 BeanDefinitions 具体是怎么样的还需要看源码
                for (Class<?> i : interfaces) {
                    // 一个接口的名称只能对应一个 bean，接口被多个实现类时，请使用自定义名称
                    beanDefinitions.add(doCreateBeanDefinition(i.getName(), clazz.getName()));
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return beanDefinitions;
    }

    private HNBeanDefinition doCreateBeanDefinition(String factoryBeanName, String className) {
        HNBeanDefinition beanDefinition = new HNBeanDefinition();
        beanDefinition.setFactoryBeanName(factoryBeanName);
        beanDefinition.setBeanClassName(className);
        return beanDefinition;
    }

    /**
     *  大小写字母的ASCII码相差32，
     *  这里首字母必须大写
     * @param name
     * @return
     */
    private String toLowerFirstCase(String name) {
        char[] chars = name.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }
}
